package cn.virens.common.mybatis.mapper.example;

import cn.virens.common.mybatis.mapper.example.base.AbstractExample;
import cn.virens.common.mybatis.mapper.example.util.Util;
import cn.virens.common.util.exception.APIException;
import org.dromara.hutool.core.text.StrUtil;

import java.util.Map;
import java.util.function.Consumer;

@SuppressWarnings("serial")
public class Example extends AbstractExample {
    private Example() {
    }

    /**
     * 设置单个字段顺序
     *
     * @param field 字段名称
     * @return 条件对象
     * @throws APIException 一般异常
     */
    public Example asc(String field) throws APIException {
        setOrderByClause(field + " ASC");

        return this;
    }

    /**
     * 设置单个字段倒序
     *
     * @param field 字段名称
     * @return 条件对象
     * @throws APIException 一般异常
     */
    public Example desc(String field) throws APIException {
        setOrderByClause(field + " DESC");

        return this;
    }

    /**
     * 获取OR模式条件构造器
     *
     * @return 条件构造器
     * @throws APIException 一般异常
     */
    public ExampleCriteria or() throws APIException {
        return addCriteria(new ExampleCriteria(Util.OR));
    }

    /**
     * 获取AND模式条件构造器
     *
     * @return 条件构造器
     * @throws APIException 一般异常
     */
    public ExampleCriteria and() throws APIException {
        return addCriteria(new ExampleCriteria(Util.AND));
    }

    /**
     * 获取OR模式条件构造器(回调实现)
     *
     * @param consumer 条件构造器回调
     * @return 条件对象
     * @throws APIException 一般异常
     */
    public Example or(Consumer<ExampleCriteria> consumer) throws APIException {
        consumer.accept(addCriteria(new ExampleCriteria(Util.OR)));

        return this;
    }

    /**
     * 获取AND模式条件构造器(回调实现)
     *
     * @param consumer 条件构造器回调
     * @return 条件对象
     * @throws APIException 一般异常
     */
    public Example and(Consumer<ExampleCriteria> consumer) throws APIException {
        consumer.accept(addCriteria(new ExampleCriteria(Util.AND)));

        return this;
    }

    /**
     * 设置group by 条件(OR)
     *
     * @param condition 条件
     * @return having构造器
     */
    public ExampleHaving havingOr(String condition) {
        return addHaving(new ExampleHaving(Util.OR, condition));
    }

    /**
     * 设置group by 条件(OR)
     *
     * @param condition 条件
     * @param value1    条件值
     * @return having构造器
     */
    public ExampleHaving havingOr(String condition, Object value1) {
        return addHaving(new ExampleHaving(Util.OR, condition, value1));
    }

    /**
     * 设置group by 条件(OR)
     *
     * @param condition 条件
     * @param value1    条件值1
     * @param value2    条件值2
     * @return having构造器
     */
    public ExampleHaving havingOr(String condition, Object value1, Object value2) {
        return addHaving(new ExampleHaving(Util.OR, condition, value1, value2));
    }

    /**
     * 设置group by 条件(AND)
     *
     * @param condition 条件
     * @return having构造器
     */
    public ExampleHaving havingAnd(String condition) {
        return addHaving(new ExampleHaving(Util.AND, condition));
    }

    /**
     * 设置group by 条件(AND)
     *
     * @param condition 条件
     * @param value1    条件值
     * @return having构造器
     */
    public ExampleHaving havingAnd(String condition, Object value1) {
        return addHaving(new ExampleHaving(Util.AND, condition, value1));
    }

    /**
     * 设置group by 条件(AND)
     *
     * @param condition 条件
     * @param value1    条件值1
     * @param value2    条件值2
     * @return having构造器
     */
    public ExampleHaving havingAnd(String condition, Object value1, Object value2) {
        return addHaving(new ExampleHaving(Util.AND, condition, value1, value2));
    }

    /**
     * LEFT连表查询
     *
     * @param table    表名
     * @param consumer 构建条件
     * @return 连表构建器
     */
    public ExampleJoin left(String table, Consumer<ExampleJoin> consumer) {
        ExampleJoin answer = addJoin(new ExampleJoin("LEFT", table));

        consumer.accept(answer);

        return answer;
    }

    /**
     * INNER连表查询
     *
     * @param table    表名
     * @param consumer 构建条件
     * @return 连表构建器
     */
    public ExampleJoin inner(String table, Consumer<ExampleJoin> consumer) {
        ExampleJoin answer = addJoin(new ExampleJoin("INNER", table));

        consumer.accept(answer);

        return answer;
    }

    /**
     * 构建条件对象
     *
     * @return 条件对象
     */
    public static Example newInstance() {
        return new Example();
    }

    /**
     * 构建条件对象
     *
     * @param map 参数map
     * @return 条件对象
     */
    public static Example of(Map<String, Object> map) throws APIException {
        return Example.newInstance().and(c -> map.forEach((k, v) -> {
            if (StrUtil.isNotEmpty(k)) c.andEqualTo(k, v);
        }));
    }

    /**
     * 构建条件对象
     *
     * @param key   条件
     * @param value 条件值
     * @return 条件对象
     */
    public static Example of(String key, Object value) throws APIException {
        return Example.newInstance().and(c -> c.andEqualTo(key, value));
    }

}
